﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.OracleClient;
using System.Data;
using NHibernate;
using dbPoll_Application.Helpers;
using NHibernate.Criterion;
using NHibernate.Linq;
using dbPoll_Application.ViewModels;

namespace dbPoll_Application.Models
{
    public static class QuestionRepository
    {

        public static IList<Question> GetQuestions()
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var questions = (from item in session.Query<Question>()
                             select item).ToList<Question>();
            return questions;
        }

        public static T GetQuestionByID<T>(int questionID) where T : Question
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            T question = (from item in session.Query<T>()
                         where item.questionID == questionID
                         select item).FirstOrDefault<T>();
            return question;
        }

        public static IList<QuestionAndPoll> GetQuestionsByTimeCreated(DateTime startTime, DateTime endTime)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var questions = (from q in session.Query<Question>()
                             from p in session.Query<Poll>()
                             where q.creationTime > startTime && q.creationTime < endTime && p.questions.Contains(q)
                             select new QuestionAndPoll(q, p)).ToList<QuestionAndPoll>();
            return questions;
        }

        public static IList<QuestionAndPoll> GetQuestionsByTimeCreatedAndPollCreator(DateTime startTime, DateTime endTime, String UserName)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var questions = (from q in session.Query<Question>()
                             from p in session.Query<Poll>()
                             from u in session.Query<User>()
                             where q.creationTime > startTime && q.creationTime < endTime && p.questions.Contains(q) && u.CreatedPolls.Contains(p) && u.UserName == UserName
                             select new QuestionAndPoll(q, p)).ToList<QuestionAndPoll>();
            return questions;
        }

        public static T GetQuestionByQuestionNumber<T>(int questionNumber, int pollID) where T : Question
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var question = (from q in session.Query<T>()
                            from p in session.Query<Poll>()
                            where q.questionNumber == questionNumber && p.pollID == pollID && p.questions.Contains(q)
                             select q).FirstOrDefault<T>();
            return question;
        }

        public static IList<QuestionAndPoll> GetQuestionsComparableWith(int questionID)
        {
            var question = QuestionRepository.GetQuestionByID<Question>(questionID);
            ISession session = NHibernateHelper.GetCurrentSession();
            var questions = (from q in session.Query<Question>()
                             from p in session.Query<Poll>()
                             where q.questionID != question.questionID
                             && q.type == question.type
                             && q.question == question.question
                             && p.questions.Contains(q)
                            select new QuestionAndPoll(q, p)).ToList<QuestionAndPoll>();
            return questions;
        }

        public static Boolean UpdateQuestion<T>(T question) where T : Question
        {
            ITransaction transaction = null;
            try
            {
                ISession session = NHibernateHelper.GetCurrentSession();
                using (transaction = session.BeginTransaction())
                {
                    session.SaveOrUpdate(question);
                    transaction.Commit();
                    return transaction.WasCommitted;
                }
            }
            catch (Exception e)
            {
                if (transaction != null)
                {
                    transaction.Rollback();
                }
            }
            return false;
        }

        public static Boolean InsertQuestion<T>(int pollID, T question) where T : Question
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                var poll = (from item in session.Query<Poll>()
                            where item.pollID == pollID
                            select item).FirstOrDefault<Poll>();
                poll.questions.Add(question);
                session.Save(poll);
                transaction.Commit();
                return transaction.WasCommitted;
            }
        }
        public static Boolean HasCompared(int questionID)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var question = (from item in session.Query<Question>()
                            where item.questionID == questionID
                            select item).FirstOrDefault<Question>();
            QuestionType type = question.type;
            Question compare=null;
            if (type==QuestionType.Custom)
                compare = (from item in session.Query<CustomQuestion>()
                           where item.compareWith!=null && item.compareWith.questionID==question.questionID
                           select item).FirstOrDefault<CustomQuestion>();
            else if (type == QuestionType.Demographic)
                compare = (from item in session.Query<DemographicQuestion>()
                           where item.compareWith != null && item.compareWith.questionID == question.questionID
                           select item).FirstOrDefault<DemographicQuestion>();
            else if (type == QuestionType.Ranking)
                compare = (from item in session.Query<RankingQuestion>()
                           where item.compareWith != null && item.compareWith.questionID == question.questionID
                           select item).FirstOrDefault<RankingQuestion>();
            if (compare != null) return true;
            else return false;
        }

        public static Boolean DeleteQuestionByID(int questionID)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                var question = (from item in session.Query<Question>()
                                where item.questionID == questionID
                                select item).FirstOrDefault<Question>();
                if (question != null)
                {
                    question.responded.Clear(); 
                    session.Delete(question);
                    transaction.Commit();
                    return true;
                }
                return false;
            }
        }

        public static Boolean DeleteOptionByID(int optionID)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                var option = (from item in session.Query<QuestionOption>()
                              where item.optionID == optionID
                              select item).FirstOrDefault<QuestionOption>();
                if (option != null)
                {
                    session.Delete(option);
                    transaction.Commit();
                    return true;
                }
                return false;
            }
        }
        public static Boolean DeleteOptions(ICollection<QuestionOption> options)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                foreach (var option in options)
                {
                    session.Delete(option);
                }
                transaction.Commit();
                return transaction.WasCommitted;
            }
        }

        public static Boolean DeleteAnswerString(CorrectAnswer answer)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Delete(answer);
                transaction.Commit();
                return transaction.WasCommitted;
            }
        }

        public static String[] GetRespondedDeviceIDs(int questionID)
        {
            var question = QuestionRepository.GetQuestionByID<Question>(questionID);
            var deviceIDs = from item in question.responded
                            select item.deviceID;
            return deviceIDs.ToArray<String>();
        }
    }
}
